home *** CD-ROM | disk | FTP | other *** search
/ El Mac 9 / El Mac 9.iso / Shareware / Applications / MathPad 2.4 / XFuns / XFun kit / Writing XFuns < prev   
Encoding:
Text File  |  1996-03-26  |  9.7 KB  |  126 lines  |  [TEXT/MPad]

  1. MathPad XFuns allow externally compiled functions to be added to the Functions menu.
  2.  
  3. The XFun kit contains interface routines and C source code for several example XFuns. CodeWarrior 8 projects are included but Think C or other development systems should be able to create Xfuns as well. The "util" folder contains general interface routines and headers.
  4.  
  5. MathPad 68K XFuns use SANE 80-bit floating point numbers. The example projects are set so that the type "double" is 80-bit.
  6.  
  7. XFun files are of type 'XFun' and creator 'MPad'. The resource fork contains one or more code resources of type 'XFun'. (Native PowerPC XFuns use the Code Fragment Manager rather that code resources. See "PPC Notes" for details.)
  8.  
  9. When MathPad is launched it checks for XFun files in the same folder as the application. Any 'XFun' code resources are loaded in.
  10.  
  11. Any named 'TEXT' resources in XFun files are added to MathPad's Help  menu. The resource name is used as the menu item. When the menu item is selected, a window with the help text will be opened. This allows XFun files to provide help info about the functions they define.
  12.  
  13. ----- See the file "mod.c" for an example of a simple XFun. --------
  14.  
  15. MathPad does a call to the beginning of the code resource on application startup. The resource header then calls main(). The parameter to main() is a callback function pointer. The main() routine is used to perform any initialization needed. Usually all it does is use the callback
  16.  
  17.   AddXfun(char *name,char *parms,funptr entry,funptr predef,...)
  18.  
  19. to install the function in MathPad. The "name" string gives the name that  MathPad will use for the new function. The "parms" string gives a formal parameter list. This parameter list appears in the menu and is used to check for the correct number of parameters. The "entry" pointer points to the code for the new function. MathPad will call the function at "entry" each time it needs to evaluate the external function. The "predef" pointer points to a function that will be called each time the document is reevaluated. If you do not need this hook, pass NULL.
  20.  
  21. When an external function is evaluated by Mathpad, the code resource's installed function is called with two parameters, a pointer to an 80-bit double for the numeric result and the callback entry point. The function should store its result and return TRUE. If the result can not be calculated it should return FALSE. (The function may also return FALSE if it passes back its results in a globals rather than the result parameter). Access to the MathPad actual parameters is via callback routines.
  22.  
  23. See the file callback.h for descriptions of the available MathPad callback routines. The file callback.c provides individual interface routines from the single callback entry point.
  24.  
  25. External functions that calculate a single result based on a few numeric parameters are quite simple and probably only require the callback
  26.  
  27.   GetParmVal(int n,double *num,funptr callback)
  28.  
  29. which gets the numeric value of parameter n. MathPad numbers its parameters in a slightly obtuse manner. Parameters are numbered from right to left starting with 0. 
  30. -------------------------------------------------------------
  31.  
  32. --- See the files "cross.c" and "histogram.c" for examples using arrays ---
  33.  
  34. Operating on arrays introduces more complication. MathPad arrays can have any number of dimensions and can be any size. Callback routines are provided to access and manipulate MathPad's general expression structure.
  35.  
  36. The callback
  37.  
  38.   MakeParmExpr(long n,EXPR *xpr,funptr callback)
  39.  
  40. makes an expression structure for parameter n. Details of this structure are not needed since there is no need to access it directly. The expression structure allocated by MakeParmExpr() must be deallocted by FreeExpr() before returning.
  41.  
  42. Accessing 1D or 2D arrays is easiest. The callback
  43.  
  44.  GetExprMatrix(EXPR xpr,double **mat,long *rows,long *cols,...)
  45.  
  46. allocates space for the matrix, evaluates all of its elements and passes back a pointer to the allocated block. An array with more than 2 dimensions will generate an error message and return false. The matrix allocated by GetExprMatrix() should be deallocated with DisposPtr().
  47.  
  48. For arrays of more than 2 dimensions or cases where it is better to evaluate individual elements, use the callbacks
  49.  
  50.  ProbeExpr(EXPR xpr,double *num,short *isarray,long *count,...)
  51.  AddIndex(EXPR *xpr,double **iptr,funptr callback)
  52.  EvalExpr(EXPR xpr,double *num,funptr callback)
  53.  
  54. The file "histogram.c" is an example of an XFun that operates on individual array elements.
  55.  
  56. XFuns can assign an array result to a global variable with the callback
  57.  
  58.  SetVarMatrix(char *name,double *arr,long rows,long cols,...)
  59.  
  60. The array must be allocated via NewPtr() and will be deallocated by MathPad. For more than 2 dimensions the callback
  61.  
  62.  FoldVar(char *name,long lim,funptr callback)
  63.  
  64. can be called any number of times to add dimensions to the array made by SetVarMatrix().
  65.  
  66. A single value can be assigned to a global with the callback
  67.  SetVarVal(char *name,double num,funptr callback)
  68.  
  69. There are also callbacks to get values from global variables.
  70.  
  71.  GetVarVal(char *name,double *num,funptr callback)
  72.  MakeVarExpr(char *name,EXPR *xpr,funptr callback)
  73.  
  74. XFuns can be set up to return fixed size arrays directly. A predef routine must be used. The callback
  75.  
  76.  AddFunDim(char *name,long lim,funptr callback)
  77.  
  78. can be called from the predef routine to tell MathPad that the named XFun will process index values. AddFunDim() can be called multiple times to setup a multidimensional function. When the XFun is called, each dimension appends an index value to the actual parameter list. The index values are accessed via GetParmVal(). An "array" function must compute its return value based on the index. MathPad only evaluates the elements that it needs and there are no guarantees as to which elements will be evaluated or what order they are evaluated in.
  79. ------------------------------------------------------
  80.  
  81. --------- A4 globals ------------------
  82.  
  83. For simple functions the XFun does not need to keep any data between calls. More complex routines will likely need to use global variables. If you use ANY global variables you will have to deal with setting up A4. By default CodeWarrior allocates strings off A4 so unless you choose PC-relative strings, you will need A4 globals just to use string constants.
  84.  
  85. 68K Mac applications access global data relative to the A5 register. Code resources are compiled separately from the application. They can't blindly store data relative to A5 since it would overwrite the application's variables. The usual solution to this is to have the code resource allocate its own global area and access it off of the A4 register. When making a code resource, the compiler generates code to use A4 rather than A5. The programmer must make sure that A4 gets set up properly whenever code from the resource is executing.
  86.  
  87. The files "A4globs.h" and "entry.c" provide a generic way to handle setting and restoring A4. These A4 files have been tried with Think C 5 and CodeWarrior 8. For other compilers you are on your own. Read the compiler manual carefully about the details of how to compile code resources. Any libraries used must be compiled for A4 globals.
  88.  
  89. A "uses globals" version of the callbacks is provided via files "callbackg.h" and "callbackg.c". If the XFun needs to use globals anyway, it is more convienient to save the callback pointer in a global rather than pass it as a parameter every time.
  90.  
  91.  
  92. --------- Error handling --------------
  93.  
  94. Execution of the XFun is not interruptable. If the calculation can take a long time, the callback
  95.  
  96.  SpinWatch()
  97.  
  98. should be used to allow computation to be switched to background or stopped via command period. If command period was hit, SpinWatch() will set the stop flag. The state of this flag can be checked with the callback
  99.  
  100.  Stopped()
  101.  
  102. The stop flag may also be set if there is a severe error when evaluating a MathPad expression. Stopped() should be checked if EvalExpr() is called in a loop. Once the stop flag is set, any attempt to evaluate a MathPad expression will immediately return false. 
  103.  
  104. The callback
  105.  
  106.  ErrMsg(char *fmt,char *str)
  107.  
  108. gives an error message for the status line. Calling ErrMsg() sets the stop flag and will cause MathPad to stop evaluation when the Xfun returns. The fmt and str get passed to sprintf(). If fmt is a simple message with no parameters, pass NULL for str. You can cheat somewhat on the value for str. You can print an integer value with ErrMsg("%ld",(char *)n).
  109.  
  110. -------- memory allocation ---------------------
  111. Usually any memory allocated by the XFun should be deallocated before returning. This applies to error returns as well as the normal return.
  112. • Expression structures allocated by MakeParmExpr() or MakeVarExpr() must be deallocated by FreeExpr(). 
  113. • MathPad allocates memory for the matrix returned by GetExprMatrix(). The Xfun must deallocate it with the toolbox call DisposPtr().
  114. • Arrays allocated and passed to SetVarMatrix() will be deallocated by MathPad and should NOT be deallocated by the XFun.
  115.  
  116. -------- multiple functions in one file ----------
  117. More than one XFun can be defined in a single Xfun file. Multiple functions can be installed from a single resource by calling AddXfun() for each function. It is also allowable to put more than one 'XFun' resource into a single Xfun file. Resource IDs do not matter (as long as they are unique).
  118.  
  119. --------- private resources -----------------------
  120. The XFun resource file is only open during MathPad startup. This means that XFuns can not expect access to private resources simply by adding them to the XFun file. Any resources in the XFun file are available during the call to main() but not during the call to the function itself. The main() routine can load resources and detach them.
  121.  
  122.  
  123. -- Send comments, questions, suggestions and bug reports to:
  124.  
  125. --       Mark.Widholm@UNH.edu
  126.